package com.twb.core.util;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * 日期时间工具类
 *
 * @version 1.0
 * @author bojiangzhou 2017-12-28
 */
/**
 * @Title Dates
 * @Description 日期时间工具类
 * @author DSY
 * @date 2018-10-17 13:49
 */
public class DateUtil {

	private static Logger logger = LoggerFactory.getLogger(DateUtil.class);

	public static Calendar calendar = Calendar.getInstance();

	/** 天 */
	public final static String DAY = "DAY";
	/** 小时 */
	public final static String HOUR = "HOUR";
	/** 分钟 */
	public final static String MINUTE = "MINUTE";
	/** 秒 */
	public final static String SECOND = "SECOND";
	/** 天 */
	public static final String TDAY = "TDAY";
	/** 周 */
	public static final String TWEEK = "TWEEK";
	/** 年 */
	public static final String TYEAR = "TYEAR";
	/** 月 */
	public static final String TMONTH = "TMONTH";

	/**
	 * 日期时间匹配格式
	 */
	public interface Pattern {
		//
		// 常规模式
		// ----------------------------------------------------------------------------------------------------
		/**
		 * yyyy-MM-dd
		 */
		String DATE = "yyyy-MM-dd";
		/**
		 * yyyy-MM-dd HH:mm:ss
		 */
		String DATETIME = "yyyy-MM-dd HH:mm:ss";
		/**
		 * yyyy-MM-dd HH:mm
		 */
		String DATETIME_MM = "yyyy-MM-dd HH:mm";
		/**
		 * yyyy-MM-dd HH:mm:ss.SSS
		 */
		String DATETIME_SSS = "yyyy-MM-dd HH:mm:ss.SSS";
		/**
		 * HH:mm
		 */
		String TIME = "HH:mm";
		/**
		 * HH:mm:ss
		 */
		String TIME_SS = "HH:mm:ss";

		//
		// 系统时间格式
		// ----------------------------------------------------------------------------------------------------
		/**
		 * yyyy/MM/dd
		 */
		String SYS_DATE = "yyyy/MM/dd";
		/**
		 * yyyy/MM/dd HH:mm:ss
		 */
		String SYS_DATETIME = "yyyy/MM/dd HH:mm:ss";
		/**
		 * yyyy/MM/dd HH:mm
		 */
		String SYS_DATETIME_MM = "yyyy/MM/dd HH:mm";
		/**
		 * yyyy/MM/dd HH:mm:ss.SSS
		 */
		String SYS_DATETIME_SSS = "yyyy/MM/dd HH:mm:ss.SSS";

		//
		// 无连接符模式
		// ----------------------------------------------------------------------------------------------------
		/**
		 * yyyyMMdd
		 */
		String NONE_DATE = "yyyyMMdd";
		/**
		 * yyyyMMddHHmmss
		 */
		String NONE_DATETIME = "yyyyMMddHHmmss";
		/**
		 * yyyyMMddHHmm
		 */
		String NONE_DATETIME_MM = "yyyyMMddHHmm";
		/**
		 * yyyyMMddHHmmssSSS
		 */
		String NONE_DATETIME_SSS = "yyyyMMddHHmmssSSS";
	}

	public static final String DEFAULT_PATTERN = Pattern.DATETIME;

	public static final String[] PARSE_PATTERNS = new String[] { Pattern.DATE, Pattern.DATETIME, Pattern.DATETIME_MM, Pattern.DATETIME_SSS, Pattern.SYS_DATE, Pattern.SYS_DATETIME, Pattern.SYS_DATETIME_MM, Pattern.SYS_DATETIME_SSS, Pattern.NONE_DATE, Pattern.NONE_DATETIME, Pattern.NONE_DATETIME_MM, Pattern.NONE_DATETIME_SSS };

	/**
	 * 格式化日期时间
	 * 
	 * @param date 日期时间
	 *
	 * @return yyyy-MM-dd HH:mm:ss
	 */
	public static String format(Date date) {
		return format(date, DEFAULT_PATTERN);
	}

	/**
	 * 格式化日期
	 * 
	 * @param date    日期(时间)
	 *
	 * @param pattern 匹配模式 参考：{@link DateUtil.Pattern}
	 *
	 * @return 格式化后的字符串
	 */
	public static String format(Date date, String pattern) {
		if (date == null) {
			return null;
		}
		pattern = StringUtils.isNotBlank(pattern) ? pattern : DEFAULT_PATTERN;
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		return sdf.format(date);
	}

	/**
	 * 解析日期
	 *
	 * @param date 日期字符串
	 *
	 * @return 解析后的日期 默认格式：yyyy-MM-dd HH:mm:ss
	 */
	public static Date parseDate(String date) {
		if (StringUtils.isBlank(date)) {
			return null;
		}
		try {
			return DateUtils.parseDate(date, PARSE_PATTERNS);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 解析日期
	 *
	 * @param date    日期
	 *
	 * @param pattern 格式 参考：{@link DateUtil.Pattern}
	 *
	 * @return 解析后的日期，默认格式：yyyy-MM-dd HH:mm:ss
	 */
	public static Date parseDate(String date, String pattern) {
		if (StringUtils.isBlank(date)) {
			return null;
		}
		String[] parsePatterns;
		parsePatterns = StringUtils.isNotBlank(pattern) ? new String[] { pattern } : PARSE_PATTERNS;
		try {
			return DateUtils.parseDate(date, parsePatterns);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * @Title  getNowStr
	 * @Description 获取当前时间
	 * @param pattern
	 * @return
	 * @author DSY
	 * @date 2018年11月29日 下午5:33:36
	 */
	public static String getNowStr(String pattern) {
		pattern = StringUtils.isNotBlank(pattern) ? pattern : DEFAULT_PATTERN;
		return format(new Date(), pattern);
	}

	/**
	 * @Title  getNowStr_NONE_DATETIME
	 * @Description 获取当前时间 yyyyMMddHHmmss
	 * @return
	 * @author DSY
	 * @date 2018年11月29日 下午5:36:47
	 */
	public static String getNowStr_NONE_DATETIME() {
		return format(new Date(), Pattern.NONE_DATETIME);
	}

	/**
	 * @Title  getNowStr_DATETIME
	 * @Description 获取当前时间 yyyy-MM-dd HH:mm:ss
	 * @return
	 * @author DSY
	 * @date 2018年11月29日 下午5:37:42
	 */
	public static String getNowStr_DATETIME() {
		return format(new Date(), Pattern.DATETIME);
	}

	/**
	 * @Title getDate
	 * @Class DateUtils.java
	 * @Description 获取服务器当前时间
	 * 
	 * @return
	 * 
	 * @author DHL
	 */
	public static Date getDate() {
		try {
			return new Date();
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * @Title getYear
	 * @Class DateUtils.java
	 * @Description 获得服务器当前日期的年份
	 * 
	 * @return
	 * 
	 * @author DHL
	 */
	public static String getYear() {
		try {
			calendar = Calendar.getInstance();
			return String.valueOf(calendar.get(Calendar.YEAR));
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * @Title getMonth
	 * @Class DateUtils.java
	 * @Description 获得服务器当前日期的月份
	 * 
	 * @return
	 * 
	 * @author DHL
	 */
	public static String getMonth() {
		try {
			calendar = Calendar.getInstance();
			java.text.DecimalFormat df = new java.text.DecimalFormat();
			df.applyPattern("00;00");
			return df.format((calendar.get(Calendar.MONTH) + 1));
		} catch (Exception e) {
			return null;
		}
	}

	/**
	 * @Title getDay
	 * @Class DateUtils.java
	 * @Description 获得服务器当前月中的天数
	 * 
	 * @return
	 * 
	 * @author DHL
	 */
	public static String getDay() {
		try {
			calendar = Calendar.getInstance();
			return String.valueOf(calendar.get(Calendar.DAY_OF_MONTH));
		} catch (Exception e) {
			logger.debug("DateUtils.getDay():" + e.getMessage());
			return null;
		}
	}

	/**
	 * @Title getSecond
	 * @Class DateUtil.java
	 * @Description 两个时间相差的秒数
	 * 
	 * @param date1
	 * @param date2
	 * @return
	 * 
	 * @author DHL
	 * @date 2016年9月22日 下午4:26:13
	 */
	public static int getSecond(Date date1, Date date2) {
		try {
			long a = date1.getTime();
			long b = date2.getTime();
			int c = (int) ((a - b) / 1000);
			return c;
		} catch (Exception e) {
			logger.debug("DateUtils.getSecond():" + e.toString());
			return 0;
		}
	}

	/**
	 * @Title getMargin
	 * @Class DateUtils.java
	 * @Description 比较两个日期相差的天数
	 * 
	 * @param date1
	 * @param date2
	 * @return
	 * 
	 * @author DHL
	 */
	public static int getMargin(String date1, String date2) {
		int margin;
		try {
			Date dt1 = str2Date(date1);
			Date dt2 = str2Date(date2);
			long l = dt1.getTime() - dt2.getTime();
			margin = (int) (l / (24 * 60 * 60 * 1000));
			return margin;
		} catch (Exception e) {
			logger.debug("DateUtils.getMargin():" + e.toString());
			return 0;
		}
	}

	/**
	 * @Title getMarginDouble
	 * @Class DateUtils.java
	 * @Description 比较两个日期相差的天数
	 * 
	 * @param date1
	 * @param date2
	 * @return
	 * 
	 * @author DHL
	 */
	public static double getMarginDouble(String date1, String date2) {
		double margin;
		try {
			Date dt1 = str2Date(date1);
			Date dt2 = str2Date(date2);
			long l = dt1.getTime() - dt2.getTime();
			margin = (l / (24 * 60 * 60 * 1000.00));
			return margin;
		} catch (Exception e) {
			logger.debug("DateUtils.getMarginDouble():" + e.toString());
			return 0;
		}
	}

	/**
	 * @Title getMonthMargin
	 * @Class DateUtils.java
	 * @Description 比较两个日期相差的月数
	 * 
	 * @param date1
	 * @param date2
	 * @return
	 * 
	 * @author DHL
	 */
	public static int getMonthMargin(String date1, String date2) {
		int margin;
		try {
			margin = (Integer.parseInt(date2.substring(0, 4)) - Integer.parseInt(date1.substring(0, 4))) * 12;
			margin += (Integer.parseInt(date2.substring(4, 7).replaceAll("-0", "-")) - Integer.parseInt(date1.substring(4, 7).replaceAll("-0", "-")));
			return margin;
		} catch (Exception e) {
			logger.debug("DateUtils.getMonthMargin():" + e.toString());
			return 0;
		}
	}

	/**
	 * @Title increaseDate
	 * @Class DateUtils.java
	 * @Description 多种方式增加时间
	 * 
	 * @param date
	 * @param increaseType （TMONTH, DAY, HOUR, MINUTE, SECOND）
	 * @param delta
	 * @return
	 * 
	 * @author DHL
	 */
	public static Date increaseDate(Date date, String increaseType, int delta) {
		Calendar cal = new java.util.GregorianCalendar();
		try {
			cal.setTime(date);
			if (increaseType.equals(TMONTH)) {
				cal.add(Calendar.MONTH, delta);
			}
			if (increaseType.equals(DAY)) {
				cal.add(Calendar.DATE, delta);
			}
			if (increaseType.equals(HOUR)) {
				cal.add(Calendar.HOUR, delta);
			}
			if (increaseType.equals(MINUTE)) {
				cal.add(Calendar.MINUTE, delta);
			}
			if (increaseType.equals(SECOND)) {
				cal.add(Calendar.SECOND, delta);
			}
			return cal.getTime();
		} catch (Exception e) {
			logger.debug("DateUtils.increaseDate():" + e.getMessage());
			return null;
		}
	}

	/**
	 * @Title isSameDay
	 * @Class DateUtils.java
	 * @Description 判断两个Date 是否同一天
	 * 
	 * @param date1
	 * @param date2
	 * @return
	 * 
	 * @author DHL
	 */
	public static Boolean isSameDay(Date date1, Date date2) {
		Calendar cal = new GregorianCalendar();
		cal.setTime(date1);
		int id1 = cal.get(Calendar.DAY_OF_YEAR);
		int iy1 = cal.get(Calendar.YEAR);
		cal.setTime(date2);
		int id2 = cal.get(Calendar.DAY_OF_YEAR);
		int iy2 = cal.get(Calendar.YEAR);
		return (id1 == id2 && iy1 == iy2);
	}

	/**
	 * @Title getOneDayRange
	 * @Class DateUtils.java
	 * @Description 用于产生指定日期的时间对。 从当天0:00:00 秒 到第二天 0:0:0 秒
	 * 
	 * @param date
	 * @return Date[0] 今天凌晨0点； Date[1] 明天凌晨零点
	 * 
	 * @author DHL
	 */
	public static Date[] getOneDayRange(Date date) {
		DateFormat df = new SimpleDateFormat(Pattern.DATE);
		Date[] d = new Date[] { null, null };
		Calendar cal = new java.util.GregorianCalendar();
		try {
			d[0] = df.parse(df.format(date));
			cal.setTime(df.parse(df.format(date)));
			cal.add(Calendar.DATE, 1);
			d[1] = cal.getTime();
			return d;
		} catch (Exception e) {
			logger.debug("DateUtils.getOneDayRange():" + e.getMessage());
			return null;
		}
	}

	/**
	 * @Title getTodayRange
	 * @Class DateUtils.java
	 * @Description 获得当天的范围
	 * 
	 * @return Date[0] 今天凌晨0点； Date[1] 明天凌晨零点
	 * 
	 * @author DHL
	 */
	public static Date[] getTodayRange() {
		return DateUtil.getOneDayRange(new Date());
	}

	/**
	 * @Title getTodayBegin
	 * @Class DateUtils.java
	 * @Description 获取今天凌晨零点的日期
	 * 
	 * @return
	 * 
	 * @author DHL
	 */
	public static Date getTodayBegin() {
		Date d[] = DateUtil.getTodayRange();
		return d[0];
	}

	/**
	 * @Title getWeekPlus
	 * @Class DateUtils.java
	 * @Description 获得当前日期与本周日相差的天数
	 * 
	 * @return
	 * 
	 * @author DHL
	 */
	private static int getWeekPlus() {
		Calendar cd = Calendar.getInstance();
		// 获得今天是一周的第几天，星期日是第一天，星期二是第二天......
		int dayOfWeek = cd.get(Calendar.DAY_OF_WEEK) - 1; // 因为按中国礼拜一作为第一天所以这里减1
		if (dayOfWeek == 1) {
			return 0;
		} else {
			return 1 - dayOfWeek;
		}
	}

	/**
	 * @Title getSundayOFWeek
	 * @Class DateUtils.java
	 * @Description 获得本周日的日期
	 * 
	 * @return
	 * 
	 * @author DHL
	 */
	public static Date getSundayOFWeek() {
		int mondayPlus = getWeekPlus() - 1;
		GregorianCalendar currentDate = new GregorianCalendar();
		currentDate.add(GregorianCalendar.DATE, mondayPlus);
		currentDate.set(GregorianCalendar.HOUR_OF_DAY, 0);
		currentDate.set(GregorianCalendar.MINUTE, 0);
		currentDate.set(GregorianCalendar.SECOND, 0);
		return currentDate.getTime();
	}

	/**
	 * @Title getMondayOFWeek
	 * @Class DateUtils.java
	 * @Description 获得本周一的日期
	 * 
	 * @return
	 * 
	 * @author DHL
	 */
	public static Date getMondayOFWeek() {
		int mondayPlus = getWeekPlus();
		GregorianCalendar currentDate = new GregorianCalendar();
		currentDate.add(GregorianCalendar.DATE, mondayPlus);
		currentDate.set(GregorianCalendar.HOUR_OF_DAY, 0);
		currentDate.set(GregorianCalendar.MINUTE, 0);
		currentDate.set(GregorianCalendar.SECOND, 0);
		return currentDate.getTime();
	}

	/**
	 * @Title getNextMonday
	 * @Class DateUtils.java
	 * @Description 获得下周星期一的日期
	 * 
	 * @return
	 * 
	 * @author DHL
	 */
	public static Date getNextMonday() {
		int mondayPlus = getWeekPlus();
		GregorianCalendar currentDate = new GregorianCalendar();
		currentDate.add(GregorianCalendar.DATE, mondayPlus + 7);
		currentDate.set(Calendar.HOUR_OF_DAY, 0);
		currentDate.set(Calendar.MINUTE, 0);
		currentDate.set(Calendar.SECOND, 0);
		return currentDate.getTime();
	}

	/**
	 * @Title getNextSunday
	 * @Class DateUtils.java
	 * @Description 获得下周星期日的日期
	 * 
	 * @return
	 * 
	 * @author DHL
	 */
	public static Date getNextSunday() {
		int mondayPlus = getWeekPlus();
		GregorianCalendar currentDate = new GregorianCalendar();
		currentDate.add(GregorianCalendar.DATE, mondayPlus + 7 + 6);
		currentDate.set(Calendar.HOUR_OF_DAY, 0);
		currentDate.set(Calendar.MINUTE, 0);
		currentDate.set(Calendar.SECOND, 0);
		return currentDate.getTime();
	}

	/**
	 * @Title getNextDay
	 * @Class DateUtils.java
	 * @Description 获得下一天的时间
	 * 
	 * @return
	 * 
	 * @author DHL
	 */
	public static Date getNextDay() {
		GregorianCalendar currentDate = new GregorianCalendar();
		currentDate.add(Calendar.DAY_OF_MONTH, 1);
		return currentDate.getTime();
	}

	/**
	 * @Title getAscendDay
	 * @Class DateUtils.java
	 * @Description 获得上一天的时间
	 * 
	 * @return
	 * 
	 * @author DHL
	 */
	public static Date getAscendDay() {
		GregorianCalendar currentDate = new GregorianCalendar();
		currentDate.add(Calendar.DAY_OF_MONTH, -1);
		return currentDate.getTime();
	}

	/**
	 * @Title getFirstDayOfMonth
	 * @Class DateUtils.java
	 * @Description 获取当月第一天
	 * 
	 * @return
	 * 
	 * @author DHL
	 */
	public static Date getFirstDayOfMonth() {
		Calendar lastDate = Calendar.getInstance();
		lastDate.set(Calendar.DATE, 1);// 设为当前月的1号
		lastDate.set(Calendar.HOUR_OF_DAY, 0);
		lastDate.set(Calendar.MINUTE, 0);
		lastDate.set(Calendar.SECOND, 0);
		return lastDate.getTime();
	}

	/**
	 * @Title getYearStart
	 * @Class DateUtils.java
	 * @Description 获得本年的开始时间
	 * 
	 * @return
	 * 
	 * @author DHL
	 */
	public static Date getYearStart() {
		GregorianCalendar currentDate = new GregorianCalendar();
		currentDate.set(GregorianCalendar.MONTH, 1);
		currentDate.set(GregorianCalendar.DAY_OF_MONTH, 1);
		currentDate.set(GregorianCalendar.HOUR_OF_DAY, 0);
		currentDate.set(GregorianCalendar.MINUTE, 0);
		currentDate.set(GregorianCalendar.SECOND, 0);
		return currentDate.getTime();
	}

	/**
	 * @Title getWeek
	 * @Class DateUtils.java
	 * @Description 根据一个日期，返回是星期几的字符串
	 * 
	 * @param date
	 * @return
	 * 
	 * @author DHL
	 */
	public static String getWeek(Date date) {
		// 再转换为时间
		Calendar c = Calendar.getInstance();
		c.setTime(date);
		// int hour=c.get(Calendar.DAY_OF_WEEK);
		// hour中存的就是星期几了，其范围 1~7
		// 1=星期日 7=星期六，其他类推
		return new SimpleDateFormat("EEEE").format(c.getTime());
	}

	/**
	 * @Title getWeekNumber
	 * @Class DateUtils.java
	 * @Description 根据一个日期，返回是星期几的数字1~7
	 * 
	 * @param date
	 * @return
	 * 
	 * @author DHL
	 */
	public static int getWeekNumber(Date date) {
		Calendar cd = Calendar.getInstance();
		cd.setTime(date);
		return cd.get(Calendar.DAY_OF_WEEK) - 1;
	}

	/**
	 * @Title getDayByStr
	 * @Class DateUtils.java
	 * @Description 获取日期字符串中的天
	 * 
	 * @param str
	 * @return
	 * 
	 * @author DHL
	 */
	public static Integer getDayByStr(String str) {
		try {
			calendar = Calendar.getInstance();
			Date date = str2Date(str);
			calendar.setTime(date);
			String day = String.valueOf(calendar.get(Calendar.DAY_OF_MONTH));
			return Integer.valueOf(day);
		} catch (Exception e) {
			logger.debug("DateUtils.getDayByStr():" + e.getMessage());
			return 0;
		}
	}

	/**
	 * @Title str2Date
	 * @Class DateUtils.java
	 * @Description 字符串转换Date
	 * 
	 * @param str Date字符串
	 * @return
	 * 
	 * @author DHL
	 */
	public static Date str2Date(String str) {
		try {
			return getDateFormat(str).parse(str);
		} catch (Exception e) {
			logger.debug("DateUtils.str2Date():" + e.getMessage());
			return null;
		}
	}

	/**
	 * @Title getDateFormat
	 * @Class DateUtils.java
	 * @Description 获取转换格式
	 * 
	 * @param str Date字符串
	 * @return
	 * 
	 * @author DHL
	 */
	public static DateFormat getDateFormat(String str) {
		str = str.trim();
		for (String key : PARSE_PATTERNS) {
			if (str.matches(key)) {
				return new SimpleDateFormat(key);
			}
		}
		return new SimpleDateFormat(DEFAULT_PATTERN);
	}

	/**
	 * @Title toMinutes
	 * @Description 毫秒转时间字符串
	 * @param milliseconds
	 * @return
	 * @author DHL
	 * @date 2021年3月18日 下午5:06:05
	 */
	public static String toTimeStr(Long milliseconds) {

		if (milliseconds == null) {
			return "";
		}
		
		if (milliseconds == 0L) {
			return "";
		}

		long hours = milliseconds / (1000 * 60 * 60);
		long minutes = (milliseconds % (1000 * 60 * 60)) / (1000 * 60);
		long seconds = (milliseconds % (1000 * 60)) / 1000;
		
		StringBuffer sb = new StringBuffer();
		
		if (hours > 0) {
			sb.append(hours).append("小时");
		}
		
		if (minutes > 0) {
			sb.append(minutes).append("分钟");
		}
		
		if (seconds > 0) {
			sb.append(seconds).append("秒");
		} else {
			sb.append("1秒");
		}

		return sb.toString();
	}
	
	/**
	 * @Title secondsToTimeStr
	 * @Description 秒转时间字符串
	 * @param seconds
	 * @return
	 * @author DHL
	 * @date 2021年4月20日 下午4:21:54
	 */
	public static String secondsToTimeStr(Long seconds) {

		if (seconds == null) {
			return "";
		}
		
		if (seconds == 0L) {
			return "";
		}

		long minutes = seconds / 60;
		long remainingSeconds = seconds % 60;
		
		StringBuffer sb = new StringBuffer();
		
		
		if (minutes > 0) {
			sb.append(minutes).append("分钟");
		}
		
		if (remainingSeconds > 0) {
			sb.append(remainingSeconds).append("秒");
		} else {
			sb.append("1秒");
		}

		return sb.toString();
	}
}